# -*- mode: python; -*-
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Author: jasonstredwick@google.com (Jason Stredwick)

"""Utility rules for building Mimic extensions on Firefox 3.6+.

Usage example:

  # Create Test Extension bundle
  # Output will be
  #     output/test_extension
  test_extension_bundle_src = 'test_extension'
  test_extension_bundle_dst = os.path.join(OUTPUT_ROOT, 'test_extension')

  print('Creating Chrome test extension bundle.')
  shutil.copytree(test_extension_bundle_src, test_extension_bundle_dst)

  # Generate for Firefox3.6+ version that mimics Test Extension.
  # The output will be
  #     output/test_extension_mimic_ff36.xpi
  alias = 'test_extension'
  id = 'test_extension2312321@mimic.com'
  creator = 'jasonstredwick@google.com (Jason Stredwick)'
  gen_firefox3_6.GenFirefox3_6('firefox3_6',
                               test_extension_bundle_dst,
                               OUTPUT_ROOT,
                               alias, id, creator)
"""


__author__ = 'jason.stredwick@gmail.com (Jason Stredwick)'


import os
import re
import shutil
import zipfile

from bite_build import deps as DEPS
from bite_build import utils


JS_COMPILE_FILES = [
  'browser_action_api.js',
  'chrome_extension.js',
  'console.js',
  'extension_api.js',
  'manifest.js',
  'module.js',
  'tab_manager.js',
  'tabs_api.js',
  'utils.js',
  'window_manager.js',
  'xhr.js',
]

DEP_JS_FILES = [
  os.path.join('common', 'extension', 'chrome', 'extension',
               'url_matching.js'),
  os.path.join('common', 'extension', 'signal', 'simple.js')
]


def GenFirefox3_6(mimic_src, chrome_extension_bundle_src, bundle_dst, xpi_dst,
                  deps, verbose, alias, id=None, creator=None,
                  deps_location=''):
  """Generate Firefox 3.6+ Mimic extension.

  This function will generate the Firefox 3.6+ Mimic extension that wraps the
  given Chrome Extension as a .xpi file:

      [alias]_mimic_ff36.xpi.

  The rules created by this function generate a number of intermediary folders
  and modified configuration files.  All of these steps conclude in generating
  an extension bundle of the entire Mimic extension and wrapped Chrome
  Extension.  This final bundle is then compressed and converted into an XPI
  file.

  Args:
    mimic_src: The location of the mimic source tree to use. (string)
    chrome_extension_bundle_src: The location for the Chrome Extension to be
        wrapped. (string)
    dst: The destination for the generated outputs. (string)
    compiler_jar: The closure compiler jar file. (string)
    alias: The name of the extension that must uniquely identify it within
        Firefox.  If the alias contains spaces they will be replaced by
        underscores. (string)
    id: An optional string used to identify the extension.  The id is used
        to register the extension and must be of the format "name@example.com".
        If an id is not supplied then it will be set to "[alias]@mimic.com".
        (string)
    creator: An optional string for the creator.  The format is typically
        "email (name)". (string)
  """
  print 'Creating Mimic of Test Extension version Firefox3.6'
  # Prepare inputs that will be used to replace keywords within certain
  # configuration files.
  if creator:
    creator = ''.join(['<em:creator>', creator, '<\/em:creator>'])
  else:
    creator = ''

  if not id:
    id = ''.join([alias, '@mimic.com'])

  alias = alias.replace(' ', '_') # Condense alias by removing all spacing.

  # Define bundle output paths
  output_root = os.path.join(bundle_dst, '%s_mimic_ff36' % alias)
  if os.path.exists(output_root):
    shutil.rmtree(output_root)

  code_src = os.path.join(mimic_src, 'chrome', 'content')
  code_dst = os.path.join(output_root, 'chrome', 'content')
  chrome_extension_bundle_dst = os.path.join(code_dst, alias)

  # Move mimic files into place.
  shutil.copytree(os.path.join(mimic_src, 'chrome', 'locale'),
                  os.path.join(output_root, 'chrome', 'locale'))
  shutil.copytree(os.path.join(mimic_src, 'chrome', 'skin'),
                  os.path.join(output_root, 'chrome', 'skin'))
  os.mkdir(os.path.join(output_root, 'chrome', 'content'))
  shutil.copy(os.path.join(code_src, 'mimic.xul'), code_dst)
  shutil.copy(os.path.join(code_src, 'xul.js'), code_dst)
  shutil.copy(os.path.join(mimic_src, 'chrome.manifest'), output_root)
  shutil.copy(os.path.join(mimic_src, 'install.rdf'), output_root)

  #   Move/Update config files with the given alias.
  chrome_src = os.path.join(mimic_src, 'chrome.manifest')
  chrome_dst = os.path.join(output_root, 'chrome.manifest')
  with open(chrome_src, 'r') as src:
    with open(chrome_dst, 'w') as dst:
      data = src.read()
      data = re.sub(r'extension_alias', alias, data)
      dst.write(data)

  install_src = os.path.join(mimic_src, 'install.rdf')
  install_dst = os.path.join(output_root, 'install.rdf')
  with open(install_src, 'r') as src:
    with open(install_dst, 'w') as dst:
      data = src.read()
      data = re.sub(r'extension_alias', alias, data)
      data = re.sub(r'extension_id', id, data)
      data = re.sub(r'creator', creator, data)
      dst.write(data)

  xul_src = os.path.join(code_src, 'xul.js')
  xul_dst = os.path.join(code_dst, 'xul.js')
  with open(xul_src, 'r') as src:
    with open(xul_dst, 'w') as dst:
      data = src.read()
      data = re.sub(r'extension_alias', alias, data)
      dst.write(data)

  # Compile Javascript
  inputs = []
  output = os.path.join(code_dst, 'mimic.js')

  dep_js_files = DEP_JS_FILES
  for f in DEP_JS_FILES:
    inputs.append(os.path.join(deps['bite'][DEPS.ROOT], f))

  for f in JS_COMPILE_FILES:
    inputs.append(os.path.join(code_src, f))

  compiler = os.path.join(deps_location,
                          deps[DEPS.CLOSURE_COMPILER][DEPS.ROOT])
  command = ['java', '-jar', '%s' % compiler,
             '--closure_entry_point mimic.module',
             '--compilation_level SIMPLE_OPTIMIZATIONS',
             '--formatting PRETTY_PRINT',
             '--generate_exports',
             '--manage_closure_dependencies',
             '--js_output_file','%s' % output,
             '--js'] + inputs
  utils.ExecuteCommand(command)

  # Add the Chrome Extension to the mimic bundle.
  shutil.copytree(chrome_extension_bundle_src, chrome_extension_bundle_dst)

  # Create .xpi of the bundle which is the format of the Firefox extensions.
  print('Creating XPI file (%s_mimic_ff36.xpi).' % alias)

  # Define bundle output paths
  xpi_root = os.path.join(xpi_dst, '%s_mimic_ff36.xpi' % alias)
  if os.path.exists(xpi_root):
    shutil.rmtree(xpi_root)

  path = os.getcwd()
  os.chdir(output_root)
  files = _GetFolderDump('.') # Determine all the files to go into the zip.
  with zipfile.ZipFile('%s_mimic_ff36.xpi' % alias, 'w') as xpizip:
    for f in files:
      xpizip.write(f)
  os.chdir(path)
  shutil.move(os.path.join(output_root, '%s_mimic_ff36.xpi' % alias), xpi_root)


def _GetFolderDump(path):
  data = []
  for f in os.listdir(path):
    f_path = os.path.join(path, f)
    if os.path.isfile(f_path):
      data.append(f_path)
    elif os.path.isdir(f_path):
      data = data + _GetFolderDump(f_path)
    else:
      print '[WARNING] Unknown file type going into zip: %s' % f_path
  return data
